/* $Id: JDatabaseTreePane.java 63 2010-02-14 13:52:34Z aaron.day $ */
package org.crazydays.gameplan.db.swing;


import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.crazydays.gameplan.db.Database;
import org.crazydays.gameplan.map.GameMap;
import org.crazydays.gameplan.model.IDatabaseObserver;
import org.crazydays.gameplan.model.IGameMapObserver;
import org.crazydays.gameplan.model.Model;

/**
 * JDatabaseTreePane
 */
public class JDatabaseTreePane
    extends JScrollPane
    implements IDatabaseObserver, IGameMapObserver
{
    /** serial version uid */
    public final static long serialVersionUID =
        "$Id: JDatabaseTreePane.java 63 2010-02-14 13:52:34Z aaron.day $"
            .hashCode();

    /** resource key: name */
    public final static String RESKEY_NAME = "DatabaseTreePane.name";

    /** resource key: icon */
    public final static String RESKEY_ICON = "DatabaseTreePane.icon";

    /** model */
    protected Model model;

    /** mouse listener */
    protected DatabaseTreeMouseListener mouseListener;

    /** tree */
    protected JTree tree;

    /** root */
    protected DatabaseNode root;

    /** maps */
    protected MapsNode maps;

    /** model */
    protected DefaultTreeModel treeModel;

    /**
     * JDatabaseTreePanel constructor.
     * 
     * @param database Database
     */
    public JDatabaseTreePane()
    {
        super(VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
    }

    /**
     * Set model.
     * 
     * @param model Model
     */
    public void setModel(Model model)
    {
        this.model = model;
    }

    /**
     * Set mouse listener.
     * 
     * @param mouseListener MouseListener
     */
    public void setMouseListener(DatabaseTreeMouseListener mouseListener)
    {
        this.mouseListener = mouseListener;
    }

    /**
     * Initialize.
     */
    public void initialize()
    {
        model.addDatabaseObserver(this);
        model.addGameMapObserver(this);
    }

    /**
     * Database opened.
     * 
     * @param database Database
     * @see IDatabaseObserver#opened(Database)
     */
    @Override
    public void opened(Database database)
    {
        loadRoot(database);
        loadMaps(database);

        setViewportView(tree);
    }

    /**
     * Load root node.
     * 
     * @param database Database
     */
    protected void loadRoot(Database database)
    {
        root = new DatabaseNode(database);
        treeModel = new DefaultTreeModel(root);

        tree = new JTree(treeModel);
        tree.addMouseListener(mouseListener);
        tree.setCellRenderer(new DatabaseTreeCellRenderer());

        tree.getSelectionModel().setSelectionMode(
            TreeSelectionModel.SINGLE_TREE_SELECTION);
    }

    /**
     * Load all maps from the database.
     * 
     * @param database Database
     */
    protected void loadMaps(Database database)
    {
        maps = new MapsNode();
        root.add(maps);

        for (GameMap gameMap : database.getGameMaps()) {
            added(gameMap);
        }

        tree.makeVisible(new TreePath(maps.getPath()));
        treeModel.nodeStructureChanged(root);
    }

    /**
     * Database closed.
     * 
     * @param database Database
     * @see IDatabaseObserver#closed(Database)
     */
    @Override
    public void closed(Database database)
    {
        setViewportView(new JPanel());

        tree = null;
        treeModel = null;
        root = null;
    }

    /**
     * Game map added.
     * 
     * @param gameMap GameMap
     * @see IGameMapObserver#added(IGameMap)
     */
    @Override
    public void added(GameMap gameMap)
    {
        MapNode node = new MapNode(gameMap);

        maps.add(node);

        tree.makeVisible(new TreePath(node.getPath()));
        treeModel.nodeStructureChanged(maps);
    }

    /**
     * Game map removed.
     * 
     * @param gameMap GameMap
     * @see IGameMapObserver#removed(IGameMap)
     */
    @Override
    public void removed(GameMap gameMap)
    {
        for (int i = 0; i < maps.getChildCount(); i++) {
            MapNode node = (MapNode) maps.getChildAt(i);

            if (gameMap.getName().equals(node.getUserObject())) {
                maps.remove(i);
                break;
            }
        }
    }
}
